#ifndef __ARRAYLIST_HPP__
#define __ARRAYLIST_HPP__

#include <string>

#include "List.hpp"

const int kInitalCapacity = 10;  // 初始容量
const int kAutoExtendCapacity = 10;  // 自动扩展容量
const double kAutoExtendThreshold = 0.75;  // 自动扩展阈值

template<typename T>
class ArrayList : List<T>
{
public:
    ArrayList()
    {
        init(kInitalCapacity);
    }

    ArrayList(int initalCapacity)
    {
        init(initalCapacity);
    }

    virtual ~ArrayList()
    {
        delete[] _elements;
    }

    void init(int initalCapacity)
    {
        _capacity = initalCapacity;
        _elements = new T[_capacity];
        _curSize = 0;
    }

    void add(const T& element)
    {
        if (_curSize+1 > kAutoExtendThreshold * _capacity)
        {
            resize(_capacity + kAutoExtendCapacity);
        }
        _elements[_curSize] = element;
        _curSize++;
    }

    void addAll(const ArrayList<T> &otherList)
    {
        // 检查大小
        if (_curSize + otherList.size() > kAutoExtendThreshold * _capacity)
        {
            resize(_capacity + otherList.size());
        }
        copyFromArray(otherList.getElements(), otherList.size(), _curSize);
        _curSize += otherList.size();
    }

    void remove(const T& element)
    {
        // TODO 暂不支持remove方法
    }

    T& operator[](int index)
    {
        return _elements[index];
    }

    int resize(int capacity = 0)
    {
        if (capacity <= 0)
        {
            capacity = _curSize;
        }

        if (capacity < _curSize)
        {
            // 新的容量不足以容纳当前的数据
            return _capacity;
        }

        T* lastElements = _elements;
        _elements = new T[capacity];
        copyFromArray(lastElements, _curSize);

        _capacity = capacity;
        delete[] lastElements;

        return _capacity;
    }

    void copyFromArray(const T* src, const int &length, int offset = 0)
    {
        for (int index=0; index<length; index++)
        {
            _elements[offset + index] = src[index];
        }
    }

    int size() const
    {
        return _curSize;
    }

    string toString()
    {
        return "ArrayList";
    }

    T* getElements() const
    {
        return _elements;
    }

private:
    T* _elements;
    int _capacity;
    int _curSize;
};

#endif
